package com.zmn.oms.business.impl.orderamount;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.zmn.coa.common.dio.OrderAmountForShopDIO;
import com.zmn.coa.common.dio.OrderBestPreferentialDIO;
import com.zmn.coa.common.dio.SubOrderPreferentialDIO;
import com.zmn.coa.common.dro.OrderBestPreferentialDRO;
import com.zmn.coa.dubbo.impl.interfaces.preferential.OrderPreferentialRemoteService;
import com.zmn.coa.dubbo.impl.interfaces.preferential.SubOrderPreferentialRemoteService;
import com.zmn.coa.dubbo.impl.interfaces.shop.ShopOrderAmountRemoteService;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.consts.GateTypeConsts;
import com.zmn.consts.GlobalConsts;
import com.zmn.dms.common.dio.coup.scenario.SendCoupScenarioDIO;
import com.zmn.dms.common.dro.coup.scenario.SendCoupScenarioBatchDRO;
import com.zmn.dms.common.dro.coup.scenario.SendCoupScenarioCouponDRO;
import com.zmn.dms.common.dro.coup.scenario.SendCoupScenarioDRO;
import com.zmn.dms.common.dto.coup.dio.coupon.CoupOnBaseInfoDIO;
import com.zmn.dms.common.dto.coup.dio.coupon.CouponConsumeDIO;
import com.zmn.dms.common.dto.coup.dio.coupon.CouponGenerateDIO;
import com.zmn.dms.common.dto.coup.dro.coupon.CoupOnBaseDRO;
import com.zmn.dms.common.dto.coup.dro.coupon.CouponConsumeDRO;
import com.zmn.dms.common.dto.preferential.dio.PreferentialDetailDIO;
import com.zmn.dms.common.dto.preferential.dro.PreferentialDetailDRO;
import com.zmn.dms.common.dto.preferential.dro.PreferentialInfoDRO;
import com.zmn.dms.common.dto.promotion.dio.PromotionDIO;
import com.zmn.dms.common.dto.promotion.dro.PromotionDRO;
import com.zmn.dms.common.dto.promotion.dro.PromotionPriceDRO;
import com.zmn.dms.common.enums.*;
import com.zmn.dms.common.enums.coup.CoupScenarioSendNodeEnums;
import com.zmn.dms.common.enums.coup.ThirdPlatEnum;
import com.zmn.dms.dubbo.interfaces.activity.ActivityInfoListRemoteService;
import com.zmn.dms.dubbo.interfaces.coup.coupon.CoupGetRemoteService;
import com.zmn.dms.dubbo.interfaces.coup.coupon.CoupModifyRemoteService;
import com.zmn.dms.dubbo.interfaces.coup.scenario.CoupScenarioModifyRemoteService;
import com.zmn.dms.dubbo.interfaces.preferential.PreferentialRemoteService;
import com.zmn.dms.dubbo.interfaces.preferential.PreferentialRuleRemoteService;
import com.zmn.dms.dubbo.interfaces.prom.PromGetRemoteService;
import com.zmn.dms.dubbo.interfaces.thrid.ThirdCouponListRemoteService;
import com.zmn.manager.redis.RedisManager;
import com.zmn.oms.business.interfaces.orderamount.OrderDiscountCalcBService;
import com.zmn.oms.common.constant.*;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.bo.orderamount.*;
import com.zmn.oms.model.entity.discount.OrderDiscount;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.performance.common.enums.OrderTimeoutTypeEnum;
import com.zmn.performance.dubbo.interfaces.order.OrderTimeoutWarningListRemoteService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 类描述：计算优惠
 * @author heciqi
 * @date 2020-06-03 14:13:35
 */
@Service
@Slf4j
public class OrderDiscountCalcBServiceImpl implements OrderDiscountCalcBService {
	private static final String TAG = "OMS-优惠计算";

	@Reference(version = com.zmn.dms.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
	private PreferentialRemoteService preferentialRemoteService;
	@Reference(version = com.zmn.dms.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
	private CoupGetRemoteService coupGetRemoteService;
	@Reference(version = com.zmn.dms.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
	private CoupScenarioModifyRemoteService coupScenarioModifyRemoteService;
	@Reference(version = com.zmn.dms.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
	private CoupModifyRemoteService coupModifyRemoteService;
	@Reference(version = com.zmn.dms.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
	private PromGetRemoteService promGetRemoteService;
	/*	@Reference(version = com.zmn.dms.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false, validation = "true")
		private ActRemoteBService actRemoteBService;*/
	@Reference(version = com.zmn.dms.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
	private ActivityInfoListRemoteService activityInfoListRemoteService;
	@Reference(version = com.zmn.dms.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
	private ThirdCouponListRemoteService thirdCouponListRemoteService;
	@Reference(version = com.zmn.performance.dubbo.consts.DubboConsts.INTERFACE_VERSION, check = false)
	private OrderTimeoutWarningListRemoteService orderTimeoutWarningListService;
	@Reference(version = com.zmn.coa.common.util.DubboConsts.INTERFACE_VERSION, check = false)
	private SubOrderPreferentialRemoteService subOrderPreferentialRemoteService;
	@Reference(version = com.zmn.coa.common.util.DubboConsts.INTERFACE_VERSION, check = false)
	private OrderPreferentialRemoteService orderPreferentialRemoteService;
	@Reference(version = com.zmn.coa.common.util.DubboConsts.INTERFACE_VERSION, check = false)
	ShopOrderAmountRemoteService shopOrderAmountRemoteService;

	@DubboReference(version = com.zmn.dms.dubbo.constant.DmsDubboConsts.INTERFACE_VERSION, check = false)
	private PreferentialRuleRemoteService preferentialRuleRemoteService;

	@Autowired
	private RedisManager redisManager;

	/**
	 * 下单
	 * 计算优惠
	 * @param calcAddOrderAmountDIO
	 * @return
	 */
	@Override
	public OrderDiscountCalcBO calcAddOrderDiscount(CalcAddOrderAmountDIO calcAddOrderAmountDIO, List<OrderDiscount> orderDiscountList) {

		// 如果是美团锁券优惠，下单后异步创建优惠
		if (Objects.equals(calcAddOrderAmountDIO.getMeiTuanDiscount(), GlobalConsts.YES)) {
			log.info("{}，美团锁券下单，不查询优惠", TAG);
			return null;
		}

		Integer originalAmount = calcAddOrderAmountDIO.getOrderAmountDIO().getOriginalAmount();

		DiscountConditionParamsDIO discountConditionParamsDIO = calcAddOrderAmountDIO.getDiscountConditionParamsDIO();
		// 渠道优惠
		if (NumberUtil.isNotNullOrZero(calcAddOrderAmountDIO.getChannelDiscountAmount())) {
			log.info("{}--渠道下单", TAG);
			OrderDiscountCalcBO channelDiscountBO = this.getChannelDiscount(discountConditionParamsDIO,
					calcAddOrderAmountDIO.getChannelDiscountAmount(), null);
			return channelDiscountBO;
		}
		// 渠道特殊优惠券
		else if (Objects.equals(calcAddOrderAmountDIO.getUnusualDiscount(), GlobalConsts.YES)) {
			log.info("{}--渠道下单--特殊优惠", TAG);
			try {
				int batchId = DiscountConsts.BATCH_ID_FREE_DISCOUNT_HQ_COMPANY; // 总公司承担批次id
				int discountRatio = 0;// 全免-0折
				Long orderId = discountConditionParamsDIO.getOrderId();
				// 发放总公司承担的全免特殊优惠券
				String itemCode = this.generateCouponDiscount(orderId, calcAddOrderAmountDIO.getDiscountConditionParamsDIO().getUserId(), discountRatio, batchId);
				// 存入redis，方便运营后台特殊优惠带值修改
				redisManager.set(String.format(RedisKeyConsts.DISCOUNT_SPECIAL_ITEMCODE_KEY, String.valueOf(orderId)), itemCode);
				redisManager.set(String.format(RedisKeyConsts.DISCOUNT_SPECIAL_DISCOUNTAMOUNT_KEY, String.valueOf(orderId)), String.valueOf(discountRatio));
				redisManager.set(String.format(RedisKeyConsts.DISCOUNT_SPECIAL_BATCHID_KEY, String.valueOf(orderId)), String.valueOf(batchId));
			} catch (OmsBaseException e) {
				log.error(e.getMessage(), e);
				return null;
			}
		}
		// 计算店铺的下单优惠
		if (NumberUtil.isNullOrZero(originalAmount)) {
			log.info("{}，没原价不计算优惠", TAG);
			return null;
		}

		// 购物车专用
		if (orderDiscountList != null){
			if (!orderDiscountList.isEmpty()) {

				orderDiscountList.forEach(e -> {
					e.setShareFlag(GlobalConsts.YES);// 标记为分摊优惠
				});
				OrderDiscountCalcBO orderDiscountCalcBO = new OrderDiscountCalcBO();
				Integer totalDiscount = orderDiscountList.stream().mapToInt(e -> e.getAmount()).sum();
				orderDiscountCalcBO.setAfterPromotionAmount(originalAmount - totalDiscount);
				orderDiscountCalcBO.setDiscountAmount(totalDiscount);// 优惠总金额
				orderDiscountCalcBO.setOrderDiscountList(orderDiscountList);// 优惠列表
				orderDiscountCalcBO.setReceiptConsumeDiscountList(orderDiscountList);// 核销列表

				// 购物车过来的优惠预付金额
				orderDiscountList.stream().filter(discount -> {
					return Objects.equals(discount.getCateg(), DiscountTypeEnums.DISCOUNT_COUP_ONCECARD.getSubType());
				}).findAny().ifPresent(discount -> {
					orderDiscountCalcBO.setDiscountPrepayAmount(NumberUtil.isNullOrZero(discount.getSellAmount()) ? null : discount.getSellAmount());
				});
				return orderDiscountCalcBO;
			} else if (!Objects.equals(GateTypeConsts.GATE_TYPE_MAP.get(calcAddOrderAmountDIO.getDiscountConditionParamsDIO().getReceiveEntranceId()), GateTypeConsts.GATE_TYPE_PLAT)) {
				// 如果不是后台下单，直接返回 如果是后台下单，走查询优惠
				log.info("{}，购物车订单，不使用优惠", TAG);
				return null;
			}
		}

		log.info("{}--入参----->{}", TAG, calcAddOrderAmountDIO);
		OrderAmountForShopDIO preferentialInfoDIO = this.convertToPreferentialForShopDIO(discountConditionParamsDIO);
		preferentialInfoDIO.setOrderAmount(originalAmount);
		Integer channelPrepayAmount = Optional.ofNullable(calcAddOrderAmountDIO)
				.map(e -> e.getOrderAmountDIO())
				.map(e -> e.getChannelPrepayAmount())
				.orElse(0);
		preferentialInfoDIO.setPrepayments(channelPrepayAmount);
		preferentialInfoDIO.setPromId(calcAddOrderAmountDIO.getPromId());
		preferentialInfoDIO.setItemCodes(Optional.ofNullable(calcAddOrderAmountDIO.getDiscountItemCodes()).orElse(Collections.emptyList()));
		preferentialInfoDIO.setInvoker(calcAddOrderAmountDIO.getInvoker() != null ? calcAddOrderAmountDIO.getInvoker() : 1);
		preferentialInfoDIO.setPreferentialDetailDIOList(Collections.emptyList());
		preferentialInfoDIO.setOnceCardcouponCode(calcAddOrderAmountDIO.getTimesCoupCode());
		ResponseDTO<PreferentialInfoDRO> preferentialRemoteInfo = shopOrderAmountRemoteService.getOrderAmountForShop(preferentialInfoDIO);
		log.info("{},店铺请求优惠接口shopOrderAmountRemoteService.getOrderAmountForShop入参--->{} 出参---->{}", TAG,
				preferentialInfoDIO, JSON.toJSONString(preferentialRemoteInfo));
		PreferentialInfoDRO preferentialInfoDRO = preferentialRemoteInfo.getData();
		if (!preferentialRemoteInfo.isSuccess() || preferentialInfoDRO == null) {
			log.error("Remote接口返回失败或数据为空：{}", preferentialRemoteInfo.getMessage());
			return null;
		}

		OrderDiscountCalcBO orderDiscountCalcBO = new OrderDiscountCalcBO();
		orderDiscountCalcBO.setAfterPromotionAmount(preferentialInfoDRO.getAfterPromotionAmount());
		orderDiscountCalcBO.setDiscountAmount(preferentialInfoDRO.getDiscountTotalAmount());// 优惠总金额
		List<OrderDiscount> orderDiscounts = this.convertToOrderDiscount(preferentialInfoDRO.getPreferentialDetailDROList(),Collections.emptyList());
		orderDiscountCalcBO.setOrderDiscountList(orderDiscounts);// 优惠列表
		orderDiscountCalcBO.setReceiptConsumeDiscountList(orderDiscounts);// 核销列表
		orderDiscountCalcBO.setLinkOfValidAll(preferentialInfoDRO.getLinkOfValidAll());// 规则链组合


		// 次卡优惠金额
		// 购物车过来的优惠预付金额
		if (CollectionUtil.isNotNullOrEmpty(orderDiscountList)) {
			orderDiscountList.stream().filter(discount -> {
				return Objects.equals(discount.getCateg(), DiscountTypeEnums.DISCOUNT_COUP_ONCECARD.getSubType());
			}).findAny().ifPresent(discount -> {
				orderDiscountCalcBO.setDiscountPrepayAmount(NumberUtil.isNullOrZero(discount.getSellAmount()) ? null : discount.getSellAmount());
			});
		}

		return orderDiscountCalcBO;
	}


	/**
	 * 重新计算优惠
	 * @param reCalcOrderAmountDIO
	 * @return
	 */
	@Override
	public OrderDiscountCalcBO reCalcDiscount(ReCalcOrderAmountDIO reCalcOrderAmountDIO) throws OmsBaseException {
		Integer originalAmount = reCalcOrderAmountDIO.getNewOriginalAmount() != null ?
				reCalcOrderAmountDIO.getNewOriginalAmount() : reCalcOrderAmountDIO.getOrderAmountDIO().getOriginalAmount();
		if (NumberUtil.isNullOrZero(originalAmount)) {
			return null;
		}

		OrderAmountDIO orderAmountDIO = reCalcOrderAmountDIO.getOrderAmountDIO();
		// 取已付金额（平台收款，渠道收款，定金）
		Integer prepayAmount = Optional.ofNullable(orderAmountDIO.getPrepayAmount()).orElse(0)
				+ Optional.ofNullable(orderAmountDIO.getChannelPrepayAmount()).orElse(0)
				+ Optional.ofNullable(orderAmountDIO.getDepositAmount()).orElse(0)
				+ Optional.ofNullable(orderAmountDIO.getPayDiscountAmount()).orElse(0);
		// 原价和已付金额相等，不计算优惠（一口价订单必须重新计算）
		if (!Objects.equals(reCalcOrderAmountDIO.getFinalPrice(), GlobalConsts.YES)) {
			if (Objects.equals(originalAmount, prepayAmount)) {
				return null;
			}
		}


//		// 一口价 已付大于原价，不计算优惠
//		if (originalAmount < prepayAmount) {
//			return null;
//		}

		// 先退还所有券
		// 外部券优惠以外的退还
		if (CollectionUtil.isNotNullOrEmpty(reCalcOrderAmountDIO.getOrderDiscountList())) {
			boolean meituanDiscount = reCalcOrderAmountDIO.getOrderDiscountList().stream()
					.anyMatch(e -> Objects.equals(e.getThirdCode(), GlobalConsts.NO)
							&& Objects.equals(e.getThirdCoupPlat(), ThirdPlatEnum.THIRD_COUP_TYPE_MT.getKey()));
			// 美团锁券不需要请求新的优惠
			if (meituanDiscount) {
				OrderDiscountCalcBO orderDiscountCalcBO = new OrderDiscountCalcBO();
				orderDiscountCalcBO.setDiscountAmount(reCalcOrderAmountDIO.getOrderDiscountList().stream().mapToInt(e -> e.getAmount()).sum());// 优惠总金额
				orderDiscountCalcBO.setOrderDiscountList(reCalcOrderAmountDIO.getOrderDiscountList());
				return orderDiscountCalcBO;
			}

			List<OrderDiscount> backDiscountList = reCalcOrderAmountDIO.getOrderDiscountList().stream()
					.filter(e -> !Objects.equals(e.getThirdCode(), GlobalConsts.YES))
					.collect(Collectors.toList());
			this.backDiscount(backDiscountList);
		}

		//SubOrderPreferentialDIO preferentialInfoDIO = this.convertToPreferentialDIO(reCalcOrderAmountDIO.getDiscountConditionParamsDIO());
		OrderBestPreferentialDIO preferentialInfoDIO = this.convertToBestPreferentialDIO(reCalcOrderAmountDIO.getDiscountConditionParamsDIO());
		preferentialInfoDIO.setInvoker(reCalcOrderAmountDIO.getInvoker() != null ? reCalcOrderAmountDIO.getInvoker() : 1);
		preferentialInfoDIO.setCurrentAmount(originalAmount);
		preferentialInfoDIO.setOriginalAmount(Optional.ofNullable(orderAmountDIO.getOriginalAmount()).orElse(0));

		if (Objects.equals(OrderConsts.ORDER_SOURCE_TYPE_MEMBER, orderAmountDIO.getSourceType())) {
			preferentialInfoDIO.setMemberFlag(OrderConsts.ORDER_SOURCE_TYPE_MEMBER);
		} else {
			preferentialInfoDIO.setMemberFlag(OrderConsts.ORDER_SOURCE_TYPE_NORMAL);
		}
		preferentialInfoDIO.setPrepayments(prepayAmount);
		// 添加迟到补偿优惠活动id
		if (NumberUtil.isNotNullOrZero(reCalcOrderAmountDIO.getDiscountConditionParamsDIO().getDiscountActivityId())) {
			if (this.checkLateWaring(reCalcOrderAmountDIO.getDiscountConditionParamsDIO().getOrderId())) {
				preferentialInfoDIO.setLateCompensationId(reCalcOrderAmountDIO.getDiscountConditionParamsDIO().getDiscountActivityId());
			}
		}
		// 添加工程师人工优惠规则ID
		if (NumberUtil.isNotNullOrZero(reCalcOrderAmountDIO.getMasterDiscountId())) {
			preferentialInfoDIO.setArtificialPromId(reCalcOrderAmountDIO.getMasterDiscountId());
		}

		// 次卡优惠券
		if (StringUtil.isNotBlank(reCalcOrderAmountDIO.getOnceCardcouponCode())) {
			preferentialInfoDIO.setOnceCardcouponCode(reCalcOrderAmountDIO.getOnceCardcouponCode());
		}

		preferentialInfoDIO.setItemCodes(StringUtil.isNotBlank(reCalcOrderAmountDIO.getCouponCode()) ? Lists.newArrayList(reCalcOrderAmountDIO.getCouponCode()) : Collections.EMPTY_LIST);
		preferentialInfoDIO.setPreferentialDetailDIOList(this.convertToPreferentialDetailDIO(reCalcOrderAmountDIO.getOrderDiscountList()));
		preferentialInfoDIO.setThirdCoupPlat(reCalcOrderAmountDIO.getThirdType());
		// 外部店铺ID
		if(StringUtil.isNotBlank(reCalcOrderAmountDIO.getExternalShopId())){
			preferentialInfoDIO.setThrShopId(reCalcOrderAmountDIO.getExternalShopId());
		}

		// 店铺电话
		if(StringUtil.isNotBlank(reCalcOrderAmountDIO.getCalledNumber())){
			preferentialInfoDIO.setShopPhone(reCalcOrderAmountDIO.getCalledNumber());
		}

		log.info("订单号{} 请求优惠接口开始=======", reCalcOrderAmountDIO.getDiscountConditionParamsDIO().getOrderId());

		log.info("[{}]，获取下单多用户最优优惠组合入参：{}",TAG,JSON.toJSONString(preferentialInfoDIO));
		ResponseDTO<OrderBestPreferentialDRO> preferentialRemoteInfo = orderPreferentialRemoteService.getOrderBestPreferential(preferentialInfoDIO);

		log.info("{},获取下单多用户最优优惠组合返回response：{}", TAG,JSON.toJSONString(preferentialRemoteInfo));

		if (!preferentialRemoteInfo.isSuccess()) {
			// 可以强制核销把金额作为异常返回，强制核销用
			if (Objects.equals(preferentialRemoteInfo.getStatus(), OmsErrorCodeConsts.ERROR_USE_COUPON_CODE)) {
				throw new OmsBaseException(OmsErrorCodeConsts.ERROR_USE_COUPON_CODE, preferentialRemoteInfo.getMessage());
			}
			log.error("Remote接口返回失败：{}", preferentialRemoteInfo.getMessage());
			throw new OmsBaseException(preferentialRemoteInfo.getMessage());
		}

		// SubOrderPreferentialDRO preferentialInfoDRO = preferentialRemoteInfo.getData();
		OrderBestPreferentialDRO preferentialInfoDRO = preferentialRemoteInfo.getData();
		List<OrderDiscount> orderDiscounts = this.convertToOrderDiscount(preferentialInfoDRO.getPreferentialDetailDROList(), reCalcOrderAmountDIO.getOrderDiscountList());// 获取可用优惠列表
		OrderDiscountCalcBO orderDiscountCalcBO = new OrderDiscountCalcBO();
		orderDiscountCalcBO.setDiscountAmount(orderDiscounts.stream().mapToInt(e -> e.getAmount()).sum());// 优惠总金额
		orderDiscountCalcBO.setOrderDiscountList(orderDiscounts);
		orderDiscountCalcBO.setReceiptConsumeDiscountList(orderDiscounts);
		orderDiscountCalcBO.setInvoker(reCalcOrderAmountDIO.getInvoker() != null ? reCalcOrderAmountDIO.getInvoker() : 1);
		//orderDiscountCalcBO.setBackDiscountList(backDiscountList); 先退回了，不需要在退回了。
		log.info("{}--条件发生变化重算优惠，结果[{}]", TAG, orderDiscountCalcBO);
		return orderDiscountCalcBO;
	}

	/**
	 * 重新计算优惠
	 * @param reCalcOrderAmountDIO
	 * @return
	 */
	@Override
	public OrderDiscountCalcBO reCalcDiscountWithNoVerify(ReCalcOrderAmountDIO reCalcOrderAmountDIO) throws OmsBaseException {
		Integer originalAmount = reCalcOrderAmountDIO.getNewOriginalAmount() != null ? reCalcOrderAmountDIO.getNewOriginalAmount() : reCalcOrderAmountDIO.getOrderAmountDIO().getOriginalAmount();
		if (NumberUtil.isNullOrZero(originalAmount)) {
			return null;
		}

		if (CollectionUtil.isNotNullOrEmpty(reCalcOrderAmountDIO.getOrderDiscountList())) {
			boolean meituanDiscount = reCalcOrderAmountDIO.getOrderDiscountList().stream()
					.anyMatch(e -> Objects.equals(e.getThirdCode(), GlobalConsts.NO)
							&& Objects.equals(e.getThirdCoupPlat(), ThirdPlatEnum.THIRD_COUP_TYPE_MT.getKey()));
			// 美团锁券不需要请求新的优惠
			if (meituanDiscount) {
				OrderDiscountCalcBO orderDiscountCalcBO = new OrderDiscountCalcBO();
				orderDiscountCalcBO.setDiscountAmount(reCalcOrderAmountDIO.getOrderDiscountList().stream().mapToInt(e -> e.getAmount()).sum());// 优惠总金额
				orderDiscountCalcBO.setOrderDiscountList(reCalcOrderAmountDIO.getOrderDiscountList());
				return orderDiscountCalcBO;
			}
		}

		OrderAmountDIO orderAmountDIO = reCalcOrderAmountDIO.getOrderAmountDIO();
		// 取已付金额（平台收款，渠道收款，定金）
		Integer prepayAmount = Optional.ofNullable(orderAmountDIO.getPrepayAmount()).orElse(0)
				+ Optional.ofNullable(orderAmountDIO.getChannelPrepayAmount()).orElse(0)
				+ Optional.ofNullable(orderAmountDIO.getDepositAmount()).orElse(0)
				+ Optional.ofNullable(orderAmountDIO.getPayDiscountAmount()).orElse(0);
		// 原价和已付金额相等，不计算优惠
		// 不判断

		// 先退还所有券
		// 外部券优惠以外的退还
		if (CollectionUtil.isNotNullOrEmpty(reCalcOrderAmountDIO.getOrderDiscountList())) {
			List<OrderDiscount> backDiscountList = reCalcOrderAmountDIO.getOrderDiscountList().stream()
					.filter(e -> !Objects.equals(e.getThirdCode(), GlobalConsts.YES))
					.collect(Collectors.toList());
			this.backDiscount(backDiscountList);
		}

		//SubOrderPreferentialDIO preferentialInfoDIO = this.convertToPreferentialDIO(reCalcOrderAmountDIO.getDiscountConditionParamsDIO());
		OrderBestPreferentialDIO preferentialInfoDIO = this.convertToBestPreferentialDIO(reCalcOrderAmountDIO.getDiscountConditionParamsDIO());
		preferentialInfoDIO.setInvoker(reCalcOrderAmountDIO.getInvoker() != null ? reCalcOrderAmountDIO.getInvoker() : 1);
		preferentialInfoDIO.setCurrentAmount(originalAmount);
		preferentialInfoDIO.setOriginalAmount(Optional.ofNullable(orderAmountDIO.getOriginalAmount()).orElse(0));

		if (Objects.equals(OrderConsts.ORDER_SOURCE_TYPE_MEMBER, orderAmountDIO.getSourceType())) {
			preferentialInfoDIO.setMemberFlag(OrderConsts.ORDER_SOURCE_TYPE_MEMBER);
		} else {
			preferentialInfoDIO.setMemberFlag(OrderConsts.ORDER_SOURCE_TYPE_NORMAL);
		}
		preferentialInfoDIO.setPrepayments(prepayAmount);
		// 添加迟到补偿优惠活动id
		if (NumberUtil.isNotNullOrZero(reCalcOrderAmountDIO.getDiscountConditionParamsDIO().getDiscountActivityId())) {
			if (this.checkLateWaring(reCalcOrderAmountDIO.getDiscountConditionParamsDIO().getOrderId())) {
				preferentialInfoDIO.setLateCompensationId(reCalcOrderAmountDIO.getDiscountConditionParamsDIO().getDiscountActivityId());
			}
		}
		// 添加工程师人工优惠规则ID
		if (NumberUtil.isNotNullOrZero(reCalcOrderAmountDIO.getMasterDiscountId())) {
			preferentialInfoDIO.setArtificialPromId(reCalcOrderAmountDIO.getMasterDiscountId());
		}
		// 次卡优惠券
		if (StringUtil.isNotBlank(reCalcOrderAmountDIO.getOnceCardcouponCode())) {
			preferentialInfoDIO.setOnceCardcouponCode(reCalcOrderAmountDIO.getOnceCardcouponCode());
		}
		preferentialInfoDIO.setItemCodes(StringUtil.isNotBlank(reCalcOrderAmountDIO.getCouponCode()) ? Lists.newArrayList(reCalcOrderAmountDIO.getCouponCode()) : Collections.EMPTY_LIST);
		preferentialInfoDIO.setPreferentialDetailDIOList(this.convertToPreferentialDetailDIO(reCalcOrderAmountDIO.getOrderDiscountList()));
		preferentialInfoDIO.setThirdCoupPlat(reCalcOrderAmountDIO.getThirdType());
		// 外部店铺ID
		if(StringUtil.isNotBlank(reCalcOrderAmountDIO.getExternalShopId())){
			preferentialInfoDIO.setThrShopId(reCalcOrderAmountDIO.getExternalShopId());
		}
		// 店铺电话
		if(StringUtil.isNotBlank(reCalcOrderAmountDIO.getCalledNumber())){
			preferentialInfoDIO.setShopPhone(reCalcOrderAmountDIO.getCalledNumber());
		}
		log.info("订单号{} 请求优惠接口开始=======", reCalcOrderAmountDIO.getDiscountConditionParamsDIO().getOrderId());

		log.info("[{}]，获取下单多用户最优优惠组合入参：{}",TAG,JSON.toJSONString(preferentialInfoDIO));
		ResponseDTO<OrderBestPreferentialDRO> preferentialRemoteInfo = orderPreferentialRemoteService.getOrderBestPreferential(preferentialInfoDIO);
		log.info("[{}],获取下单多用户最优优惠组合返回response：{}", TAG, JSON.toJSONString(preferentialRemoteInfo));

		if (!preferentialRemoteInfo.isSuccess()) {
			// 可以强制核销把金额作为异常返回，强制核销用
			if (Objects.equals(preferentialRemoteInfo.getStatus(), OmsErrorCodeConsts.ERROR_USE_COUPON_CODE)) {
				throw new OmsBaseException(OmsErrorCodeConsts.ERROR_USE_COUPON_CODE, preferentialRemoteInfo.getMessage());
			}
			log.error("Remote接口返回失败：{}", preferentialRemoteInfo.getMessage());
			throw new OmsBaseException(preferentialRemoteInfo.getMessage());
		}

		// SubOrderPreferentialDRO preferentialInfoDRO = preferentialRemoteInfo.getData();
		OrderBestPreferentialDRO preferentialInfoDRO = preferentialRemoteInfo.getData();
		List<OrderDiscount> orderDiscounts = this.convertToOrderDiscount(preferentialInfoDRO.getPreferentialDetailDROList(), reCalcOrderAmountDIO.getOrderDiscountList());// 获取可用优惠列表
		OrderDiscountCalcBO orderDiscountCalcBO = new OrderDiscountCalcBO();
		orderDiscountCalcBO.setDiscountAmount(orderDiscounts.stream().mapToInt(e -> e.getAmount()).sum());// 优惠总金额
		orderDiscountCalcBO.setOrderDiscountList(orderDiscounts);
		orderDiscountCalcBO.setReceiptConsumeDiscountList(orderDiscounts);
		orderDiscountCalcBO.setInvoker(reCalcOrderAmountDIO.getInvoker() != null ? reCalcOrderAmountDIO.getInvoker() : 1);
		//orderDiscountCalcBO.setBackDiscountList(backDiscountList); 先退回了，不需要在退回了。
		log.info("{}--条件发生变化重算优惠，结果[{}]", TAG, orderDiscountCalcBO);
		return orderDiscountCalcBO;
	}

	/**
	 * 核销优惠
	 * @param orderDiscounts
	 * @param compulsoryFlag 是否强制验券，1否，2是
	 * @return
	 */
	@Override
	public Integer receiptConsumeDiscount(List<OrderDiscount> orderDiscounts, Integer invoker, Integer originalAmount, OrderWork orderWork, Integer compulsoryFlag,String thrShopId,String shopPhone) throws OmsBaseException {
		if (CollectionUtil.isNullOrEmpty(orderDiscounts)) {
			return null;
		}
		// 取核销列表，优惠券和内部券才核销
		List<OrderDiscount> list = orderDiscounts.stream()
				.filter(e -> StringUtils.isNotBlank(e.getItemCode()))
				.collect(Collectors.toList());
		if (CollectionUtil.isNullOrEmpty(list)) {
			return null;
		}

		List<CoupOnBaseInfoDIO> coupOnBaseinfoDIOList =Lists.newArrayListWithCapacity(list.size());
		list.forEach(e->{
			CoupOnBaseInfoDIO coupOnBaseinfoDIO = new CoupOnBaseInfoDIO();
			coupOnBaseinfoDIO.setFactAmount(e.getAmount());
			coupOnBaseinfoDIO.setCouponCode(e.getItemCode());
			coupOnBaseinfoDIO.setThirdCoupPlat(e.getThirdCoupPlat());
			coupOnBaseinfoDIO.setShareFlag(NumberUtil.isNotNullOrZero(e.getShareFlag()) ? e.getShareFlag() : GlobalConsts.NO);
			coupOnBaseinfoDIOList.add(coupOnBaseinfoDIO);
		});

		CouponConsumeDIO coupOnConsumeDIO = new CouponConsumeDIO();
		coupOnConsumeDIO.setBizType(BusinessUseTypeEnums.O2O.getKey());
		coupOnConsumeDIO.setCoupOnBaseInfoDIOList(coupOnBaseinfoDIOList);
		coupOnConsumeDIO.setOrderId(orderWork.getOrderId());
		coupOnConsumeDIO.setUserId(orderWork.getUserId());
		coupOnConsumeDIO.setAmount(Optional.ofNullable(originalAmount).orElse(0));
		coupOnConsumeDIO.setChannelId(orderWork.getChannelId());
		coupOnConsumeDIO.setProductId(orderWork.getShowProductId());
		coupOnConsumeDIO.setCityId(orderWork.getCityId());
		coupOnConsumeDIO.setMasterId(orderWork.getMasterId());
		coupOnConsumeDIO.setInvoker(Optional.ofNullable(invoker).orElse(1));
		coupOnConsumeDIO.setCompulsoryFlag(compulsoryFlag);

		// 外部店铺ID
		if(StringUtil.isNotBlank(thrShopId)){
			coupOnConsumeDIO.setThrShopId(thrShopId);
		}
		// 店铺电话
		if(StringUtil.isNotBlank(shopPhone)){
			coupOnConsumeDIO.setShopPhone(shopPhone);
		}
		// 包含外部券
		/*boolean includeKoubei = list.stream().anyMatch(e -> Objects.equals(e.getThirdCode(), GlobalConsts.YES)
				&& (Objects.equals(e.getThirdCoupPlat(), ThirdPlatEnum.THIRD_COUP_TYPE_KB.getKey()) || Objects.equals(e.getThirdCoupPlat(), ThirdPlatEnum.THIRD_COUP_TYPE_MT.getKey()))
				&& StringUtils.isNotBlank(e.getItemCode()));*/
		ResponseDTO<List<CouponConsumeDRO>> listResponseDTO;
		try {
			log.info("[{}]，核销内部、外部优惠券入参：{}",TAG,JSON.toJSONString(coupOnConsumeDIO));
			listResponseDTO = coupModifyRemoteService.receiptConsume(coupOnConsumeDIO);
			log.info("[{}]，核销内部、外部优惠券返回response：{}",TAG,JSON.toJSONString(listResponseDTO));
		} catch (Exception e) {
			log.error("核销异常", e.getMessage(), e);
			throw new OmsBaseException("优惠券核销失败--请重试");
		}
		if (!listResponseDTO.isSuccess()) {
			// 可以强制核销把金额作为异常返回，强制核销用
			if (Objects.equals(listResponseDTO.getStatus(), OmsErrorCodeConsts.ERROR_USE_COUPON_CODE)) {
				throw new OmsBaseException(OmsErrorCodeConsts.ERROR_USE_COUPON_CODE, listResponseDTO.getMessage());
			}
			throw new OmsBaseException(listResponseDTO.getMessage());
		}
		log.info("{}listResponseDTO--核销完成", TAG);

		// 口碑验券核销后才有销售价格
		if (CollectionUtil.isNotNullOrEmpty(listResponseDTO.getData())) {
			CouponConsumeDRO couponConsumeDRO = listResponseDTO.getData().get(0);
			if (Objects.isNull(couponConsumeDRO)) {
				return null;
			}
			return Optional.ofNullable(couponConsumeDRO.getSalePrice()).orElse(GlobalConsts.NONE);
		} else {
			return null;
		}
	}

	/**
	 * 获取第三方验券的售价（获取售价后DMS队列通知到OMS更新售价）
	 * @param orderId
	 * @param cityId
	 * @param channelId
	 * @param itemCode
	 */
	@Override
	public void getThirdSellAmount(Long orderId, Integer cityId, Integer channelId, String itemCode) {
		ResponseDTO<Integer> thirdCouponSalePrice = thirdCouponListRemoteService.getThirdCouponSalePrice(orderId, cityId, channelId, itemCode);
		log.info("thirdCouponListRemoteService.getThirdCouponSalePrice 获取美团售价==>orderId:{} cityId:{} channelId :{}itemCode:{}，出参:{}",
				orderId, cityId, channelId, itemCode, JSON.toJSONString(thirdCouponSalePrice));
	}


	/**
	 * 归还优惠
	 * @param orderDiscounts
	 * @return
	 */
	@Override
	public void backDiscount(List<OrderDiscount> orderDiscounts) {
		if (CollectionUtil.isNullOrEmpty(orderDiscounts)) {
			return;
		}
		List<String> itemCodes = orderDiscounts.stream()
				.filter(e -> StringUtils.isNotBlank(e.getItemCode()))
				.map(e -> e.getItemCode())
				.collect(Collectors.toList());
		if (CollectionUtil.isNullOrEmpty(itemCodes)) {
			return;
		}

		Long orderId = orderDiscounts.get(0).getOrderId();
		ResponseDTO responseDTO = coupModifyRemoteService.resumeCoupon(itemCodes, 2, orderId);
		log.info("{}--退还优惠券coupModifyRemoteService#resumeCoupon，入参[{}] 出参[{}]", TAG, itemCodes, JSON.toJSONString(responseDTO));
		if (!responseDTO.isSuccess()) {
			log.error("{}--退还失败", TAG);
		}

	}

	/**
	 * 作废优惠
	 * @param orderDiscounts
	 * @return
	 */
	@Override
	public void obsDiscount(List<OrderDiscount> orderDiscounts) {
		if (CollectionUtil.isNullOrEmpty(orderDiscounts)) {
			return;
		}
		List<String> itemCodes = orderDiscounts.stream()
				.filter(e -> StringUtils.isNotBlank(e.getItemCode()))
				.map(e -> e.getItemCode())
				.collect(Collectors.toList());
		if (CollectionUtil.isNullOrEmpty(itemCodes)) {
			return;
		}
		Long orderId = orderDiscounts.get(0).getOrderId();
		this.obsDiscountItemCodes(itemCodes,orderId);
	}

	/**
	 * 作废优惠
	 * @param itemCodes
	 * @return
	 */
	@Override
	public void obsDiscountItemCodes(List<String> itemCodes,Long orderId) {
		if (CollectionUtil.isNullOrEmpty(itemCodes)) {
			return;
		}

		ResponseDTO responseDTO = coupModifyRemoteService.resumeCoupon(itemCodes, 3, orderId);
		log.info("{}--作废优惠券coupModifyRemoteService#resumeCoupon，入参[{}] 出参[{}]", TAG, itemCodes, JSON.toJSONString(responseDTO));
		if (!responseDTO.isSuccess()) {
			log.error("{}--作废失败", TAG);
		}
	}

	/**
	 * 获取渠道优惠
	 * @param discountConditionParamsDIO
	 * @param discountAmount 优惠金额
	 * @param orderDiscountList 已有优惠
	 * @return
	 */
	@Override
	public OrderDiscountCalcBO getChannelDiscount(DiscountConditionParamsDIO discountConditionParamsDIO,
												  Integer discountAmount, List<OrderDiscount> orderDiscountList) {
		SendCoupScenarioDIO sendCoupScenarioDIO = new SendCoupScenarioDIO();
		sendCoupScenarioDIO.setOrderId(discountConditionParamsDIO.getOrderId());
		sendCoupScenarioDIO.setSendNode(CoupScenarioSendNodeEnums.CHANNEL_DISCOUNT_NODE.getKey());
		sendCoupScenarioDIO.setChannelId(discountConditionParamsDIO.getChannelId());
		sendCoupScenarioDIO.setCityId(discountConditionParamsDIO.getCityId());
		sendCoupScenarioDIO.setUserType(UserTypeEnums.PERSONAL_USER.getKey());
		sendCoupScenarioDIO.setUserId(discountConditionParamsDIO.getUserId());
		sendCoupScenarioDIO.setPreferentialType(PreferentialTypeEnums.FULL_REDUCTION.getKey());
		sendCoupScenarioDIO.setPreferentialAmount(discountAmount);
		sendCoupScenarioDIO.setProductId(discountConditionParamsDIO.getShowProductId());
		//sendCoupScenarioDIO.setOrderEntrance();
		ResponseDTO<SendCoupScenarioDRO> sendCoupScenarioDROResponseDTO;
		try {
			sendCoupScenarioDROResponseDTO = coupScenarioModifyRemoteService.sendCoupScenarioCoupToUser(sendCoupScenarioDIO);
			log.info("{}--获取渠道优惠券coupScenarioModifyRemoteService#sendCoupScenarioCoupToUser，入参[{}] 出参[{}]", TAG,
					sendCoupScenarioDIO, JSON.toJSONString(sendCoupScenarioDROResponseDTO));
			if (!sendCoupScenarioDROResponseDTO.isSuccess()) {
				return null;
			}
		} catch (Exception e) {
			log.error("获取渠道优惠券 异常" + e.getMessage(),e);
			return null;
		}

		OrderDiscount channelDiscount = this.convertChannelDiscountToOrderDiscount(sendCoupScenarioDROResponseDTO.getData().getUserReceiveBatchList().get(0));
		if (orderDiscountList == null) {
			orderDiscountList = Lists.newArrayList();
		}
		orderDiscountList.add(channelDiscount);
		OrderDiscountCalcBO orderDiscountCalcBO = new OrderDiscountCalcBO();
		orderDiscountCalcBO.setDiscountAmount(orderDiscountList.stream().mapToInt(e -> e.getAmount()).sum());
		orderDiscountCalcBO.setOrderDiscountList(orderDiscountList);
		orderDiscountCalcBO.setReceiptConsumeDiscountList(Lists.newArrayList(channelDiscount));
		return orderDiscountCalcBO;
	}

	/**
	 * 获取特殊优惠
	 * @param orderId
	 * @param userId
	 * @param discountRatio
	 * @return 券码
	 */
	@Override
	public String generateCouponDiscount(Long orderId, Long userId, Integer discountRatio,Integer bathId) throws OmsBaseException {
		CouponGenerateDIO build = CouponGenerateDIO.builder()
				.batchId(bathId)
				.bizType(BusinessTakeTypeEnums.SPECIAL_DISCOUNT.getKey())
				.bizNo(String.valueOf(orderId))
				.discountRatio(discountRatio)
				.userId(userId)
				.count(1)
				.build();
		ResponseDTO<CoupOnBaseDRO> responseDTO = coupGetRemoteService.generateCouponByBatchId(build);
		log.info("{}--生成特殊优惠券coupGetRemoteService#generateCouponByBatchId，入参[{}] 出参[{}]", TAG, build, JSON.toJSONString(responseDTO));
		if (!responseDTO.isSuccess()) {
			throw new OmsBaseException("生成特殊优惠券失败 [" + responseDTO.getMessage() + "]");
		}
		return responseDTO.getData().getCouponCode();
	}

	/**
	 * 获取人工优惠
	 *
	 * @param triggerAmountChangeEnum
	 * @param calcOrderAmountDIO
	 * @return
	 * @throws OmsBaseException
	 */
	@Override
	public OrderDiscountCalcBO getArtificialDiscount(TriggerAmountChangeEnum triggerAmountChangeEnum, ReCalcOrderAmountDIO calcOrderAmountDIO) throws OmsBaseException {

		OrderAmountDIO orderAmountDIO = calcOrderAmountDIO.getOrderAmountDIO();
		List<OrderDiscount> orderDiscountList = calcOrderAmountDIO.getOrderDiscountList();
		// 后台人工优惠和工程师人工优惠
		Integer promId = null;
		if (CollectionUtil.isNotNullOrEmpty(orderDiscountList)) {
			promId = orderDiscountList.stream()
					.filter(e -> Objects.equals(e.getCateg(), DiscountConsts.DISCOUNT_CATEG_PROM))
					.findFirst().map(e -> e.getItemId()).orElse(null);
		}

		PromotionDIO promotionDIO = this.convertToPromotionDIO(calcOrderAmountDIO.getDiscountConditionParamsDIO());
		promotionDIO.setPromId(promId);
		promotionDIO.setOrderAmount(orderAmountDIO.getOriginalAmount());
		promotionDIO.setArtificialDiscountTyp(TriggerAmountChangeEnum.ARTIFICIAL_MASTER_DISCOUNT == triggerAmountChangeEnum ? 1 : 2);
		ResponseDTO<PromotionDRO> artificialProms = promGetRemoteService.getArtificialProms(promotionDIO);
		if (!artificialProms.isSuccess()) {
			throw new OmsBaseException("人工优惠失败 [" + artificialProms.getMessage() + "] ");
		}

		// 排除之前的人工优惠
		orderDiscountList = orderDiscountList.stream()
				.filter(e->!Objects.equals(e.getCateg(), DiscountConsts.DISCOUNT_CATEG_ARTIFICIAL))
				.collect(Collectors.toList());

		// 人工优惠
		Integer bachId = TriggerAmountChangeEnum.ARTIFICIAL_OPERATE_DISCOUNT == triggerAmountChangeEnum ? DiscountConsts.BATCH_ID_ARTIFICIAL_STAFF : DiscountConsts.BATCH_ID_ARTIFICIAL_MASTER;
		OrderDiscount artificialOrderDiscount = this.convertPromotionDIOToOrderDiscount(artificialProms.getData(), calcOrderAmountDIO.getNewArtificialDiscountAmount(),bachId);
		orderDiscountList.add(artificialOrderDiscount);

		OrderDiscountCalcBO orderDiscountCalcBO = new OrderDiscountCalcBO();
		orderDiscountCalcBO.setDiscountAmount(orderDiscountList.stream().filter(e -> e.getAmount() != null).mapToInt(e -> e.getAmount()).sum());
		orderDiscountCalcBO.setOrderDiscountList(orderDiscountList);
		orderDiscountCalcBO.setReceiptConsumeDiscountList(Collections.emptyList());// 无需核销
		return orderDiscountCalcBO;
	}

	/**
	 * 返回迟到补偿金额
	 *
	 * @return
	 */
	@Override
	public Integer getLateAmount(Long orderId, Integer activeId) {
		if (NumberUtil.isNullOrZero(activeId)) {
			return null;
		}
		if (!this.checkLateWaring(orderId)) {
			return null;
		}
		// 满足迟到赔偿金额
		ResponseDTO<Integer> lateCompensationAmountByOrderIdAndActId = activityInfoListRemoteService.getLateCompensationAmountByOrderIdAndActId(orderId, activeId);
		log.info("{}--获取迟到金额activityInfoListRemoteService#getLateCompensationAmountByOrderIdAndActId，入参[{},{}] 出参[{}]", TAG, orderId, activeId, JSON.toJSONString(lateCompensationAmountByOrderIdAndActId));
		if (!lateCompensationAmountByOrderIdAndActId.isSuccess()) {
			log.error("{}remote获取迟到金额[{}]", TAG, lateCompensationAmountByOrderIdAndActId.getMessage());
			return null;
		}
		return lateCompensationAmountByOrderIdAndActId.getData();
	}

	/**
	 * 获取人工最大优惠
	 *
	 * @return
	 */
	@Override
	public Integer getArtificialMaxDiscount(TriggerAmountChangeEnum triggerAmountChangeEnum, ReCalcOrderAmountDIO calcOrderAmountDIO) throws OmsBaseException {
		OrderAmountDIO orderAmountDIO = calcOrderAmountDIO.getOrderAmountDIO();
		Integer originalAmount = orderAmountDIO.getOriginalAmount();
		Integer prepayAmount = Optional.ofNullable(orderAmountDIO.getPrepayAmount()).orElse(0);
		Integer channelPrepayAmount = Optional.ofNullable(orderAmountDIO.getChannelPrepayAmount()).orElse(0);
		prepayAmount = prepayAmount + channelPrepayAmount;
		Integer depositAmount = Optional.ofNullable(orderAmountDIO.getDepositAmount()).orElse(0);
		Integer masterAmount = Optional.ofNullable(orderAmountDIO.getMasterAmount()).orElse(0);

		Integer discountAmount = 0;
		Integer promId = null;
		List<OrderDiscount> selectedOrderDiscountList = calcOrderAmountDIO.getOrderDiscountList();
		if (CollectionUtil.isNotNullOrEmpty(selectedOrderDiscountList)) {
			// 获取优惠总额（排除人工优惠）
			discountAmount = selectedOrderDiscountList.stream()
					.filter(e -> !Objects.equals(e.getCateg(), DiscountConsts.DISCOUNT_CATEG_ARTIFICIAL) && !Objects.equals(e.getSourceId(), DiscountConsts.BATCH_ID_FREE_DISCOUNT_HQ_COMPANY)
							&& !Objects.equals(e.getSourceId(), DiscountConsts.BATCH_ID_FREE_DISCOUNT_SUB_COMPANY))
					.mapToInt(e -> e.getAmount())
					.sum();
			// 获取促销id
			promId = selectedOrderDiscountList.stream()
					.filter(e -> Objects.equals(e.getCateg(), DiscountConsts.DISCOUNT_CATEG_PROM))
					.findFirst().map(e -> e.getItemId()).orElse(null);
		}

		// 最大优惠金额
		Integer maxDiscountAmount = 0;

		//   A：订单金额 / 产品数量 ≤ 50 元 或 优惠类型：全免优惠,Xiewenbing 2019.11.30
		//   则 MAX 优惠金额 = 订单金额 - 预付款 - 定金 - 其他优惠金额
		if (Objects.equals(TriggerAmountChangeEnum.ARTIFICIAL_OPERATE_FREE_DISCOUNT, triggerAmountChangeEnum)) {
			if (originalAmount != null) {
				maxDiscountAmount = originalAmount - prepayAmount - depositAmount - discountAmount;
			} else {
				return 0;
			}
			/*if (productCount != null) {
				boolean supportFree = MathUtil.div(originalAmount, productCount, 2) <= 5000;
				if (supportFree) {
					maxDiscountAmount = originalAmount - prepayAmount - depositAmount - discountAmount;
				}
			}*/
		} else {
			if (NumberUtil.isNullOrZero(originalAmount)) {
				return 0;
			}

			PromotionDIO promotionDIO = this.convertToPromotionDIO(calcOrderAmountDIO.getDiscountConditionParamsDIO());
			promotionDIO.setPromId(promId);
			promotionDIO.setOrderAmount(originalAmount);
			promotionDIO.setArtificialDiscountTyp(TriggerAmountChangeEnum.ARTIFICIAL_MASTER_DISCOUNT == triggerAmountChangeEnum ? 1 : 2);
			ResponseDTO<PromotionPriceDRO> promotionPriceDROResponseDTO = promGetRemoteService.calculationArtificialPrice(promotionDIO);
			log.info("{}--获取人工优惠promGetRemoteService#calculationArtificialPrice，入参[{}] 出参[{}]", TAG, promotionDIO, JSON.toJSONString(promotionPriceDROResponseDTO));
			if (!promotionPriceDROResponseDTO.isSuccess()) {
				throw new OmsBaseException(StringUtils.defaultIfBlank(promotionPriceDROResponseDTO.getMessage(),"人工优惠失败"));
			}

			// 当前最大可优惠金额
			Integer currentMaxDiscountAmountTwo = originalAmount - prepayAmount - depositAmount - discountAmount;
			// 人工优惠可最大优惠金额
			Integer artificialMaxDiscountAmount1 = promotionPriceDROResponseDTO.getData().getMaxDiscountAmount();
			maxDiscountAmount = NumberUtil.toInteger(Math.min(currentMaxDiscountAmountTwo, artificialMaxDiscountAmount1));
		}

		// 若人工优惠 > 订单金额-预付款-定金，则最大优惠金额 = 订单金额-预付款-定金 - 其他优惠，反之，最大优惠金额 = 折扣
		if (maxDiscountAmount > (originalAmount - prepayAmount - depositAmount)) {
			maxDiscountAmount = originalAmount - prepayAmount - depositAmount - discountAmount;
		}
		return maxDiscountAmount;
	}

	@Override
	public Integer getPromId(TriggerAmountChangeEnum triggerAmountChangeEnum, ReCalcOrderAmountDIO calcOrderAmountDIO) throws OmsBaseException {
		OrderAmountDIO orderAmountDIO = calcOrderAmountDIO.getOrderAmountDIO();
		Integer originalAmount = orderAmountDIO.getOriginalAmount();

		Integer discountAmount = 0;
		Integer promId = null;
		List<OrderDiscount> selectedOrderDiscountList = calcOrderAmountDIO.getOrderDiscountList();
		if (CollectionUtil.isNotNullOrEmpty(selectedOrderDiscountList)) {
			// 获取优惠总额（排除人工优惠）
			discountAmount = selectedOrderDiscountList.stream()
					.filter(e -> !Objects.equals(e.getCateg(), DiscountConsts.DISCOUNT_CATEG_ARTIFICIAL) && !Objects.equals(e.getSourceId(), DiscountConsts.BATCH_ID_FREE_DISCOUNT_HQ_COMPANY)
							&& !Objects.equals(e.getSourceId(), DiscountConsts.BATCH_ID_FREE_DISCOUNT_SUB_COMPANY))
					.mapToInt(e -> e.getAmount())
					.sum();
			// 获取促销id
			promId = selectedOrderDiscountList.stream()
					.filter(e -> Objects.equals(e.getCateg(), DiscountConsts.DISCOUNT_CATEG_PROM))
					.findFirst().map(e -> e.getItemId()).orElse(null);
		}


		if (NumberUtil.isNullOrZero(originalAmount)) {
			return 0;
		}

		PromotionDIO promotionDIO = this.convertToPromotionDIO(calcOrderAmountDIO.getDiscountConditionParamsDIO());
		promotionDIO.setPromId(promId);
		promotionDIO.setOrderAmount(originalAmount);
		promotionDIO.setArtificialDiscountTyp(TriggerAmountChangeEnum.ARTIFICIAL_MASTER_DISCOUNT == triggerAmountChangeEnum ? 1 : 2);
		ResponseDTO<PromotionPriceDRO> promotionPriceDROResponseDTO = promGetRemoteService.calculationArtificialPrice(promotionDIO);
		log.info("{}--【获取优惠券Id】获取人工优惠promGetRemoteService#calculationArtificialPrice，入参[{}] 出参[{}]", TAG, promotionDIO, JSON.toJSONString(promotionPriceDROResponseDTO));
		if (!promotionPriceDROResponseDTO.isSuccess() || Objects.isNull(promotionPriceDROResponseDTO.getData())) {
			throw new OmsBaseException(StringUtils.defaultIfBlank(promotionPriceDROResponseDTO.getMessage(),"人工优惠失败"));
		}

		return promotionPriceDROResponseDTO.getData().getPromId();
	}


	/**
	 * 检测人工优惠
	 *
	 * @param calcOrderAmountDIO
	 * @return
	 */
	@Override
	public ResponseDTO<Boolean> checkArtificialDiscount(ReCalcOrderAmountDIO calcOrderAmountDIO) {
		try {
			Integer artificialMaxDiscount = this.getArtificialMaxDiscount(TriggerAmountChangeEnum.ARTIFICIAL_OPERATE_DISCOUNT, calcOrderAmountDIO);
			return ResponseDTO.success(true);
		} catch (OmsBaseException e) {
			log.error("人工优惠接口返回=>[{}]", e.getMessage());
			return ResponseDTO.fail("配置不支持人工优惠");
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return ResponseDTO.fail("人工优惠使用异常");
		}
	}

	/**
	 * 获取非人工优惠的优惠
	 *
	 * @param orderDiscountList
	 * @return
	 */
	@Override
	public OrderDiscountCalcBO getDeleteArtificialDiscount(List<OrderDiscount> orderDiscountList) {

		// 删除人工优惠后的优惠
		orderDiscountList = orderDiscountList.stream()
				.filter(e -> !Objects.equals(e.getCateg(), DiscountConsts.DISCOUNT_CATEG_ARTIFICIAL) && !Objects.equals(e.getSourceId(), DiscountConsts.BATCH_ID_FREE_DISCOUNT_HQ_COMPANY)
						&& !Objects.equals(e.getSourceId(), DiscountConsts.BATCH_ID_FREE_DISCOUNT_SUB_COMPANY)
				)
				.collect(Collectors.toList());

		OrderDiscountCalcBO orderDiscountCalcBO = new OrderDiscountCalcBO();
		orderDiscountCalcBO.setDiscountAmount(orderDiscountList.stream().mapToInt(e -> e.getAmount()).sum());
		orderDiscountCalcBO.setOrderDiscountList(orderDiscountList);
		orderDiscountCalcBO.setReceiptConsumeDiscountList(Collections.emptyList());// 无需核销
		return orderDiscountCalcBO;
	}

	/**
	 * 获取非人工优惠的优惠
	 *
	 * @param orderDiscountList
	 * @return
	 */
	@Override
	public OrderDiscountCalcBO getDeleteMaterArtificialDiscount(List<OrderDiscount> orderDiscountList) {

		// 删除人工优惠后的优惠
		orderDiscountList = orderDiscountList.stream()
				.filter(e -> !Objects.equals(e.getCateg(), DiscountConsts.DISCOUNT_CATEG_ARTIFICIAL))
				.collect(Collectors.toList());

		OrderDiscountCalcBO orderDiscountCalcBO = new OrderDiscountCalcBO();
		orderDiscountCalcBO.setDiscountAmount(orderDiscountList.stream().mapToInt(e -> e.getAmount()).sum());
		orderDiscountCalcBO.setOrderDiscountList(orderDiscountList);
		orderDiscountCalcBO.setReceiptConsumeDiscountList(Collections.emptyList());// 无需核销
		return orderDiscountCalcBO;
	}

	/**
	 * 获取删除所有的优惠后的优惠（渠道优惠例外）
	 * @param orderDiscountList
	 * @return
	 */
	@Override
	public OrderDiscountCalcBO getDeleteAllDiscount(List<OrderDiscount> orderDiscountList, Integer fullPaymentFlag) {

		if (CollectionUtil.isNotNullOrEmpty(orderDiscountList)) {
			boolean meituanDiscount = orderDiscountList.stream()
					.anyMatch(e -> Objects.equals(e.getThirdCode(), GlobalConsts.NO)
							&& Objects.equals(e.getThirdCoupPlat(), ThirdPlatEnum.THIRD_COUP_TYPE_MT.getKey()));
			// 美团锁券不需要请求新的优惠
			if (meituanDiscount) {
				OrderDiscountCalcBO orderDiscountCalcBO = new OrderDiscountCalcBO();
				orderDiscountCalcBO.setDiscountAmount(orderDiscountList.stream().mapToInt(e -> e.getAmount()).sum());// 优惠总金额
				orderDiscountCalcBO.setOrderDiscountList(orderDiscountList);
				return orderDiscountCalcBO;
			}
		}

		// 渠道优惠和外部券优惠例外，不能删除
		List<OrderDiscount> avaDiscountList = orderDiscountList.stream()
				.filter(e -> Objects.equals(e.getCateg(), DiscountConsts.DISCOUNT_CATEG_CHANNEL)
						|| Objects.equals(e.getThirdCode(), GlobalConsts.YES))
				.collect(Collectors.toList());

		// 渠道优惠和外部券优惠以外的退还
		List<OrderDiscount> backDiscountList = orderDiscountList.stream()
				.filter(e -> !(Objects.equals(e.getCateg(), DiscountConsts.DISCOUNT_CATEG_CHANNEL)
						|| Objects.equals(e.getThirdCode(), GlobalConsts.YES)))
				.collect(Collectors.toList());

		// 如果下单是全款（保留除人工优惠以外的其他优惠）
		// 是否有次卡优惠券
		boolean isHaveTimesCoup = orderDiscountList.stream().anyMatch(e -> Objects.equals(e.getCateg(), DiscountTypeEnums.DISCOUNT_COUP_ONCECARD.getSubType()));
		if (Objects.equals(GlobalConsts.YES, fullPaymentFlag)
				&& !isHaveTimesCoup) {
			avaDiscountList = orderDiscountList.stream()
					.filter(e -> !Objects.equals(e.getCateg(), DiscountConsts.DISCOUNT_CATEG_ARTIFICIAL))
					.collect(Collectors.toList());

			// 不退还优惠券
			backDiscountList = Lists.newArrayList();
		}


		OrderDiscountCalcBO orderDiscountCalcBO = new OrderDiscountCalcBO();
		orderDiscountCalcBO.setDiscountAmount(avaDiscountList.stream().mapToInt(e -> e.getAmount()).sum());
		orderDiscountCalcBO.setOrderDiscountList(avaDiscountList);
		orderDiscountCalcBO.setBackDiscountList(backDiscountList);
		orderDiscountCalcBO.setReceiptConsumeDiscountList(Collections.emptyList());// 无需核销
		return orderDiscountCalcBO;
	}

	/**
	 * 检测是否配置了迟到补偿优惠
	 * @return
	 */
	@Override
	public boolean checkLateCompensationDiscount(Integer cityId, Integer channelId, Integer showProductId) {
		try {
			ResponseDTO<Integer> hasLateCompensation = activityInfoListRemoteService.hasLateCompensation(cityId, channelId, showProductId);
			log.info("{}--获取人工优惠activityInfoListRemoteService#hasLateCompensation，入参cityId[{}]channelId[{}]showProductId[{}] 出参[{}]", TAG, cityId, channelId, showProductId, JSON.toJSONString(hasLateCompensation));
			if (!hasLateCompensation.isSuccess()) {
				return false;
			}
			return Objects.equals(GlobalConsts.YES, hasLateCompensation.getData());
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return false;
		}
	}

	/**
	 * 删除redis特殊优惠券
	 * @param orderId
	 */
	@Override
	public void delRedisSpecialDiscountCoupon(Long orderId) {
		String redisItemCodeKey = String.format(RedisKeyConsts.DISCOUNT_SPECIAL_ITEMCODE_KEY, String.valueOf(orderId));
		boolean isExists = redisManager.exists(redisItemCodeKey);
		if (isExists) {
			redisManager.del(redisItemCodeKey);
			String redisDiscountAmountKey = String.format(RedisKeyConsts.DISCOUNT_SPECIAL_DISCOUNTAMOUNT_KEY, String.valueOf(orderId));
			redisManager.del(redisDiscountAmountKey);
			String redisBathIdKey = String.format(RedisKeyConsts.DISCOUNT_SPECIAL_BATCHID_KEY, String.valueOf(orderId));
			redisManager.del(redisBathIdKey);
		}
	}

	private List<PreferentialDetailDIO> convertToPreferentialDetailDIO(List<OrderDiscount> orderDiscounts) {
		List<PreferentialDetailDIO> list = Lists.newArrayList();
		for (OrderDiscount orderDiscount : orderDiscounts) {
			PreferentialDetailDIO preferentialDetailDIO = new PreferentialDetailDIO();
			preferentialDetailDIO.setId(orderDiscount.getItemId());
			preferentialDetailDIO.setType(orderDiscount.getCateg());
			preferentialDetailDIO.setBatchId(orderDiscount.getSourceId());
			preferentialDetailDIO.setDiscountAmount(0);
			preferentialDetailDIO.setActualOrderAmount(orderDiscount.getAmount());
			preferentialDetailDIO.setItemCode(orderDiscount.getItemCode());
			preferentialDetailDIO.setPreferentialType(DiscountConsts.convertToDMSDiscountType(orderDiscount.getType()));
			preferentialDetailDIO.setShareFlag(orderDiscount.getShareFlag());
			if (Objects.equals(orderDiscount.getThirdCode(), GlobalConsts.YES)) {
				try {
					PreferentialDetailDRO preferentialDetailDRO = JSON.parseObject(orderDiscount.getSourceData(), PreferentialDetailDRO.class);
					preferentialDetailDIO.setSalePrice(preferentialDetailDRO.getSalePrice());
					preferentialDetailDIO.setDiscountAmount(preferentialDetailDRO.getDiscountAmount());
					preferentialDetailDIO.setItemThirdCode(preferentialDetailDRO.getItemThirdCode());
				} catch (Exception ex) {
					log.error("转回对象失败", ex.getMessage(), ex);
				}
			}
			preferentialDetailDIO.setThirdCode(orderDiscount.getThirdCode() != null ? orderDiscount.getThirdCode() : GlobalConsts.NO);
			preferentialDetailDIO.setBizNo(orderDiscount.getOrderId() + "");
			preferentialDetailDIO.setBizType(BusinessUseTypeEnums.O2O.getKey());
			list.add(preferentialDetailDIO);
		}
		return list;
	}

	private OrderAmountForShopDIO convertToPreferentialForShopDIO(DiscountConditionParamsDIO discountConditionParamsDIO) {
		OrderAmountForShopDIO preferentialInfoInfDIO = BeanMapper.map(discountConditionParamsDIO, OrderAmountForShopDIO.class);
		preferentialInfoInfDIO.setPlat(discountConditionParamsDIO.getPlat());
		preferentialInfoInfDIO.setOrderId(discountConditionParamsDIO.getOrderId());
		preferentialInfoInfDIO.setProductIds(Lists.newArrayList(discountConditionParamsDIO.getShowProductId()));
		preferentialInfoInfDIO.setOrderTime(discountConditionParamsDIO.getReceiveTime());
		preferentialInfoInfDIO.setBizType(discountConditionParamsDIO.getBizType());
		preferentialInfoInfDIO.setInWarranty(discountConditionParamsDIO.getBizType());
		preferentialInfoInfDIO.setOutWarranty(Objects.equals(discountConditionParamsDIO.getBizType(),com.zmn.consts.GlobalConsts.BIZ_TYPE_F) ? GlobalConsts.NO : GlobalConsts.YES);
		int tariff = Objects.equals(discountConditionParamsDIO.getServItemType(), OrderConsts.SERVICE_ITEM_TYPE_FAULT) ? GlobalConsts.YES : GlobalConsts.NO;
		preferentialInfoInfDIO.setTariffOnoff(tariff);
		preferentialInfoInfDIO.setUntariffOnoff(tariff == GlobalConsts.YES ? GlobalConsts.NO : GlobalConsts.YES);
		int extendedWarranty = discountConditionParamsDIO.getMember() != null ? discountConditionParamsDIO.getMember() : GlobalConsts.NO;
		preferentialInfoInfDIO.setExtendedWarranty(extendedWarranty);
		preferentialInfoInfDIO.setUnextendedWarranty(Objects.equals(extendedWarranty, GlobalConsts.YES) ? GlobalConsts.NO : GlobalConsts.YES);

		preferentialInfoInfDIO.setBrandId(discountConditionParamsDIO.getBrandId());

		return preferentialInfoInfDIO;
	}

	private SubOrderPreferentialDIO convertToPreferentialDIO(DiscountConditionParamsDIO discountConditionParamsDIO) {
		SubOrderPreferentialDIO preferentialInfoInfDIO = BeanMapper.map(discountConditionParamsDIO, SubOrderPreferentialDIO.class);
		preferentialInfoInfDIO.setPlat(discountConditionParamsDIO.getPlat());
		preferentialInfoInfDIO.setOrderId(discountConditionParamsDIO.getOrderId());
		//preferentialInfoInfDIO.setProductId(discountConditionParamsDIO.getShowProductId());
		preferentialInfoInfDIO.setProductIds(Lists.newArrayList(discountConditionParamsDIO.getShowProductId()));
		preferentialInfoInfDIO.setOrderTime(discountConditionParamsDIO.getReceiveTime());
		preferentialInfoInfDIO.setBizType(discountConditionParamsDIO.getBizType());
		preferentialInfoInfDIO.setSpecialDiscountFlag(discountConditionParamsDIO.getSpecialDiscountFlag());
		//preferentialInfoInfDIO.setInWarranty(discountConditionParamsDIO.getBizType());
		//preferentialInfoInfDIO.setOutWarranty(Objects.equals(discountConditionParamsDIO.getBizType(),com.zmn.consts.GlobalConsts.BIZ_TYPE_F) ? GlobalConsts.NO : GlobalConsts.YES);
		int tariff = Objects.equals(discountConditionParamsDIO.getServItemType(), OrderConsts.SERVICE_ITEM_TYPE_FAULT) ? GlobalConsts.YES : GlobalConsts.NO;
		preferentialInfoInfDIO.setTariffOnoff(tariff);
		preferentialInfoInfDIO.setUntariffOnoff(tariff == GlobalConsts.YES ? GlobalConsts.NO : GlobalConsts.YES);
		int extendedWarranty = discountConditionParamsDIO.getMember() != null ? discountConditionParamsDIO.getMember() : GlobalConsts.NO;
		preferentialInfoInfDIO.setExtendedWarranty(extendedWarranty);
		preferentialInfoInfDIO.setUnextendedWarranty(Objects.equals(extendedWarranty, GlobalConsts.YES) ? GlobalConsts.NO : GlobalConsts.YES);
		return preferentialInfoInfDIO;
	}

	private OrderBestPreferentialDIO convertToBestPreferentialDIO(DiscountConditionParamsDIO discountConditionParamsDIO) {
		OrderBestPreferentialDIO preferentialInfoInfDIO = BeanMapper.map(discountConditionParamsDIO, OrderBestPreferentialDIO.class);
		List<Long> userIds = Lists.newArrayList(discountConditionParamsDIO.getUserId());
		if (NumberUtil.isNotNullOrZero(discountConditionParamsDIO.getVisitUserId())) {
			userIds.add(discountConditionParamsDIO.getVisitUserId());// 支持扫码用户找最优优惠
		}
		preferentialInfoInfDIO.setUserIds(userIds);
		preferentialInfoInfDIO.setPlat(discountConditionParamsDIO.getPlat());
		preferentialInfoInfDIO.setOrderId(discountConditionParamsDIO.getOrderId());
		//preferentialInfoInfDIO.setProductId(discountConditionParamsDIO.getShowProductId());
		preferentialInfoInfDIO.setProductIds(Lists.newArrayList(discountConditionParamsDIO.getShowProductId()));
		preferentialInfoInfDIO.setOrderTime(DateUtil.getNow());
		preferentialInfoInfDIO.setBizType(discountConditionParamsDIO.getBizType());
		preferentialInfoInfDIO.setSpecialDiscountFlag(discountConditionParamsDIO.getSpecialDiscountFlag());
		//preferentialInfoInfDIO.setInWarranty(discountConditionParamsDIO.getBizType());
		//preferentialInfoInfDIO.setOutWarranty(Objects.equals(discountConditionParamsDIO.getBizType(),com.zmn.consts.GlobalConsts.BIZ_TYPE_F) ? GlobalConsts.NO : GlobalConsts.YES);
		int tariff = Objects.equals(discountConditionParamsDIO.getServItemType(), OrderConsts.SERVICE_ITEM_TYPE_FAULT) ? GlobalConsts.YES : GlobalConsts.NO;
		preferentialInfoInfDIO.setTariffOnoff(tariff);
		preferentialInfoInfDIO.setUntariffOnoff(tariff == GlobalConsts.YES ? GlobalConsts.NO : GlobalConsts.YES);
		int extendedWarranty = discountConditionParamsDIO.getMember() != null ? discountConditionParamsDIO.getMember() : GlobalConsts.NO;
		preferentialInfoInfDIO.setExtendedWarranty(extendedWarranty);
		preferentialInfoInfDIO.setUnextendedWarranty(Objects.equals(extendedWarranty, GlobalConsts.YES) ? GlobalConsts.NO : GlobalConsts.YES);
		preferentialInfoInfDIO.setServItemType(discountConditionParamsDIO.getServItemType());
		return preferentialInfoInfDIO;
	}

	private List<OrderDiscount> convertToOrderDiscount(List<PreferentialDetailDRO> list, List<OrderDiscount> selectedOrderDiscounts) {
		if (list == null) {
			return Lists.newArrayList();
		}

		// 获取已有的外部券优惠
		OrderDiscount outCouponOrderDiscount = selectedOrderDiscounts.stream()
				.filter(e -> Objects.equals(e.getThirdCode(), GlobalConsts.YES))
				.findFirst()
				.orElse(null);
		List<OrderDiscount> orderDiscounts = Lists.newArrayListWithCapacity(list.size());
		for (PreferentialDetailDRO preferentialDetailDRO : list) {
			// 已有外部券，不使用接口返回的，防止计算错误
			if (outCouponOrderDiscount != null && Objects.equals(preferentialDetailDRO.getThirdCode(), GlobalConsts.YES)) {
				orderDiscounts.add(outCouponOrderDiscount);
				continue;
			}

			Integer actualOrderAmount = preferentialDetailDRO.getActualOrderAmount();
			Integer sellAmount = Optional.ofNullable(preferentialDetailDRO.getSalePrice()).orElse(0);
			String remark = "";
			if (Objects.equals(preferentialDetailDRO.getThirdCode(), GlobalConsts.YES)) {
				log.info("外部券优惠金额==>actualOrderAmount[{}]", actualOrderAmount);
				//remark = String.format("验券->面值%s，售价%s,扣减售价后实际优惠金额%s", preferentialDetailDRO.getDiscountAmount(), sellAmount, actualOrderAmount);
				if (StringUtils.isNotBlank(preferentialDetailDRO.getItemThirdCode())) {
					remark = "券号 " + preferentialDetailDRO.getItemThirdCode();
				}
			}
			OrderDiscount orderDiscount = new OrderDiscount();
			orderDiscount.setCateg(preferentialDetailDRO.getType());
			orderDiscount.setCategName(preferentialDetailDRO.getTypeName());
			orderDiscount.setType(DiscountConsts.convertToOMSDiscountType(preferentialDetailDRO.getPreferentialType()));
			orderDiscount.setAmount(actualOrderAmount);
			orderDiscount.setTypeDesc("");
			orderDiscount.setItemId(preferentialDetailDRO.getId());
			orderDiscount.setItemCode(preferentialDetailDRO.getItemCode());
			//orderDiscount.setSellAmount(sellAmount);
			orderDiscount.setThirdCode(preferentialDetailDRO.getThirdCode() != null ? preferentialDetailDRO.getThirdCode() : GlobalConsts.NO);
			orderDiscount.setRedeemCode(preferentialDetailDRO.getRedeemCode());// 兑换码
			orderDiscount.setDmsDiscountId(preferentialDetailDRO.getId());
			orderDiscount.setServiceId(preferentialDetailDRO.getServiceId());
			orderDiscount.setSourceId(preferentialDetailDRO.getBatchId());
			orderDiscount.setSourceData(JSON.toJSONString(preferentialDetailDRO));
			orderDiscount.setThirdCoupPlat(preferentialDetailDRO.getThirdCoupPlat());
			orderDiscount.setShareFlag(NumberUtil.isNotNullOrZero(preferentialDetailDRO.getShareFlag()) ?preferentialDetailDRO.getShareFlag() : GlobalConsts.NO);
			orderDiscount.setRemark(remark);

			if (Objects.equals(preferentialDetailDRO.getType(), DiscountTypeEnums.DISCOUNT_COUP_ONCECARD.getSubType())) {
				orderDiscount.setTimesCardSellAmount(sellAmount);
				orderDiscount.setSellAmount(sellAmount);
			}

			orderDiscounts.add(orderDiscount);
		}
		return orderDiscounts;
	}


	// private OrderDiscount convertCoupOnBaseDROToOrderDiscount(CoupOnBaseDRO coupOnBaseDRO) {
	// 	OrderDiscount orderDiscount = new OrderDiscount();
	// 	orderDiscount.setCateg(coupOnBaseDRO.getCoupType());
	// 	orderDiscount.setCategName(coupOnBaseDRO.getCoupTypeName());
	// 	orderDiscount.setType(DiscountConsts.convertToOMSDiscountType(coupOnBaseDRO.getPreferentialType()));
	// 	orderDiscount.setAmount(coupOnBaseDRO.getAmount());
	// 	orderDiscount.setTypeDesc(coupOnBaseDRO.getDesc());
	// 	orderDiscount.setItemId(coupOnBaseDRO.getCouponId());
	// 	orderDiscount.setItemCode(coupOnBaseDRO.getCouponCode());
	// 	orderDiscount.setThirdCode(GlobalConsts.NO);
	// 	orderDiscount.setSourceId(coupOnBaseDRO.getBatchId());
	// 	orderDiscount.setSourceData(JSON.toJSONString(coupOnBaseDRO));
	// 	orderDiscount.setRemark("");
	// 	return orderDiscount;
	// }

	private OrderDiscount convertChannelDiscountToOrderDiscount(SendCoupScenarioBatchDRO sendCoupScenarioBatchDRO) {
		OrderDiscount orderDiscount = new OrderDiscount();
		orderDiscount.setCateg(sendCoupScenarioBatchDRO.getCoupType());
		//orderDiscount.setCategName(coupOnBaseDRO.getCoupTypeName());
		orderDiscount.setType(DiscountConsts.convertToOMSDiscountType(sendCoupScenarioBatchDRO.getPreferentialType()));
		orderDiscount.setTypeDesc(sendCoupScenarioBatchDRO.getBatchName());
		List<SendCoupScenarioCouponDRO> couponList = sendCoupScenarioBatchDRO.getCouponList();
		if (CollectionUtil.isNullOrEmpty(sendCoupScenarioBatchDRO.getCouponList())) {
			log.error("无优惠券信息------->{}", JSON.toJSONString(sendCoupScenarioBatchDRO));
			return null;
		}

		SendCoupScenarioCouponDRO sendCoupScenarioCouponDRO = couponList.get(0);
		orderDiscount.setItemId(sendCoupScenarioCouponDRO.getCouponId());
		orderDiscount.setItemCode(sendCoupScenarioCouponDRO.getCouponCode());
		orderDiscount.setAmount(sendCoupScenarioCouponDRO.getFaceValue());
		orderDiscount.setThirdCode(GlobalConsts.NO);
		orderDiscount.setSourceId(sendCoupScenarioBatchDRO.getBatchId());
		orderDiscount.setSourceData(JSON.toJSONString(sendCoupScenarioBatchDRO));
		orderDiscount.setRemark(sendCoupScenarioBatchDRO.getDesc());
		return orderDiscount;
	}

	private OrderDiscount convertPromotionDIOToOrderDiscount(PromotionDRO promotionDRO,Integer discountAmount,Integer batchId) {
		OrderDiscount orderDiscount = new OrderDiscount();
		orderDiscount.setCateg(promotionDRO.getType());
		orderDiscount.setCategName(promotionDRO.getType()+"");
		orderDiscount.setType(DiscountConsts.convertToOMSDiscountType(promotionDRO.getMode()));
		orderDiscount.setAmount(discountAmount);
		orderDiscount.setTypeDesc(promotionDRO.getDesc());
		orderDiscount.setItemId(promotionDRO.getId());
		orderDiscount.setItemCode("");
		orderDiscount.setThirdCode(GlobalConsts.NO);
		orderDiscount.setSourceId(batchId);
		orderDiscount.setSourceData(JSON.toJSONString(promotionDRO));
		orderDiscount.setRemark("");
		return orderDiscount;
	}

	private PromotionDIO convertToPromotionDIO(DiscountConditionParamsDIO discountConditionParamsDIO) {
		PromotionDIO promotionDIO = BeanMapper.map(discountConditionParamsDIO, PromotionDIO.class);
		promotionDIO.setProductId(discountConditionParamsDIO.getShowProductId());
		// TODO xy bizType
		promotionDIO.setInWarranty(discountConditionParamsDIO.getBizType());
		promotionDIO.setOutWarranty(Objects.equals(discountConditionParamsDIO.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_F) ? GlobalConsts.NO : GlobalConsts.YES);
		int tariff = Objects.equals(discountConditionParamsDIO.getServItemType(), OrderConsts.SERVICE_ITEM_TYPE_FAULT) ? GlobalConsts.YES : GlobalConsts.NO;
		promotionDIO.setTariffOnoff(tariff);
		promotionDIO.setUntariffOnoff(tariff == GlobalConsts.YES ? GlobalConsts.NO : GlobalConsts.YES);
		promotionDIO.setExtendedWarranty(GlobalConsts.NO);
		promotionDIO.setUnextendedWarranty(GlobalConsts.YES);
		return promotionDIO;
	}

	/**
	 * 检测迟到预警
	 * @param orderId
	 * @return
	 */
	private boolean checkLateWaring(Long orderId) {
		// 是否上门超时
		ResponseDTO<Boolean> visitTimeout = orderTimeoutWarningListService.checkOrderTimeoutStatus(orderId, OrderTimeoutTypeEnum.VISIT);
		log.debug("{}--是否上门超时orderTimeoutWarningListService#checkOrderTimeoutStatus，入参[{}，{}] 出参[{}]", TAG, orderId, OrderTimeoutTypeEnum.VISIT, JSON.toJSONString(visitTimeout));
		if (visitTimeout.isSuccess() && visitTimeout.getData()) {
			return true;
		}
		return false;
		// 是否提前上门
		// ResponseDTO<Boolean> early = orderTimeoutWarningListService.checkOrderTimeoutStatus(orderId, OrderTimeoutTypeEnum.VISIT_EARLY);
		// log.info("{}--是否提前上门orderTimeoutWarningListService#checkOrderTimeoutStatus，入参[{}，{}] 出参[{}]", TAG, orderId, OrderTimeoutTypeEnum.VISIT_EARLY,JSON.toJSONString(early));
		// if (early.isSuccess() && early.getData()) {
		// 	return true;
		// }
	}

	public static void main(String[] args) {
		List<Object> collect = Collections.emptyList().stream().collect(Collectors.toList());

		DiscountTypeEnums msgType = DiscountTypeEnums.values()[1];

		BusinessUseTypeEnums businessUseTypeEnums = BusinessUseTypeEnums.values()[1];

		System.out.println(msgType);
	}
}
